home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / documents / video / lurker / ij / ij.h < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  14.7 KB  |  351 lines

  1. /*
  2.  * ij.h - device-independent input jacks for VL
  3.  *
  4.  * this is a simple hack API.  you pick a VL device.  you get a list of
  5.  * available input jacks as text strings.  you pick one.  the hack will
  6.  * create a path from a properly configured video source node to the
  7.  * drain node you give.  hopefully someday the VL will offer this
  8.  * functionality built-in so that developers do not have to deal with
  9.  * this level of device-dependence.
  10.  *
  11.  * this hack also lets you pick the default jack and see what that was.
  12.  *
  13.  * WARNING this version has not been tested for all jacks for all devices.
  14.  */
  15.  
  16. #include <dmedia/vl.h>
  17.  
  18. typedef struct _IJhandle *IJhandle;
  19.  
  20. /*
  21.  * open a handle to use to pick input jacks.  at this point you
  22.  * specify a VLServer, and you specify what device you'll be using 
  23.  * (VL_ANY for the default device).
  24.  *
  25.  * if you'd just like to present a list of device names, you can use
  26.  * something like this snippet:
  27.  *
  28.   {
  29.     VLDevList devlist;
  30.     
  31.     vlGetDeviceList(vlServer, &devlist);
  32.     
  33.     for (dv=0; dv < (int)devlist.numDevices; dv++)
  34.       printf("the device with VLDev %d is called [%s]\n",  
  35.              devlist.devices[dv].dev,
  36.              devlist.devices[dv].name);
  37.   }
  38.  * 
  39.  * the VLDev (not the index dv) is what you pass to ijOpenHandle.
  40.  *
  41.  * during this call, ij may scan the hardware to see which flavor of a
  42.  * board you have, and which options are really present.  instead of
  43.  * exposing the (often misleading) VL device name to the user, you can
  44.  * get ij to give you a much more meaningful name (the marketing name
  45.  * for the flavor of board the user has installed) with this snippet:
  46.  *
  47.   {
  48.     VLDevList devlist;
  49.     
  50.     vlGetDeviceList(vlServer, &devlist);
  51.     
  52.     for (dv=0; dv < (int)devlist.numDevices; dv++)
  53.       {
  54.         VLDev dev = devlist.devices[dv].dev;
  55.         
  56.         VLNode drain_node = vlGetNode(vlServer, VL_DRN, VL_MEM, VL_ANY);
  57.         IJhandle h = ijOpenHandle(vlServer, dev, drain_node);
  58.         
  59.         printf("device with VLDev %d: VL calls it [%s]"
  60.                " but it's really [%s]\n",  
  61.                devlist.devices[dv].dev,
  62.                devlist.devices[dv].name
  63.                ijGetDeviceName(h));
  64.         
  65.         ijCloseHandle(h);
  66.       }
  67.   }
  68.  *
  69.  * ij will use the VLServer and VLDev passed in for other functions
  70.  * you call in the lifetime of this IJhandle.
  71.  *
  72.  * NOTE: you must also specify the handle to a drain node of the kind you
  73.  * will be using (screen, memory, etc.).   this VLNode is not saved in
  74.  * the IJhandle and thus it will not be used by future ij calls unless
  75.  * you pass the same VLNode in again.  ij may need to use this drain_node 
  76.  * in order to probe the device to find out its capabilities, and in 
  77.  * order to translate VL_ANY to an actual default device.  In these cases,
  78.  * ijOpenHandle will actually create, set up, and destroy a path using your
  79.  * drain_node.  The VL leaves us no alternative to doing this.  ij uses 
  80.  * VL_READ_ONLY, VL_READ_ONLY when setting up the path, so in theory this
  81.  * should not interfere with the VL preemption mechanism.  There is one 
  82.  * more caveat that results from this: VL has a limitation where it cannot
  83.  * deal with the same VLNode handle being used on a path on different 
  84.  * devices.  Therefore, once you pass drain_node into ijOpenHandle, 
  85.  * you should never use that node handle again.  You can call vlGetNode 
  86.  * with the same arguments to get a new handle that refers to the same
  87.  * resources.  This is shown in the code snippet above.  
  88.  *
  89.  * NOTE: in most cases, the hardware inventory information available
  90.  * to ij is derived from a scan done at BOOT TIME.  Therefore, if
  91.  * the user plugs in some dongle, break-out-box, or digital camera 
  92.  * after the machine has booted, it may not be included in ij's list 
  93.  * of jacks (the user must reboot to get the jacks listed).
  94.  */
  95. IJhandle ijOpenHandle(VLServer svr,        /* required */
  96.                       VLDev device,        /* VL_ANY for default device */
  97.                       VLNode drain_node);  /* drain node you'll use on path */
  98.  
  99. /*
  100.  * ijCloseHandle deallocates ij's resources for this handle:
  101.  * it does not destroy any VL nodes or paths.
  102.  */
  103. void ijCloseHandle(IJhandle h);
  104.  
  105. /*
  106.  * returns the VLDev chosen.  useful if you specified VL_ANY to ijOpenHandle
  107.  */
  108. int ijGetVLDev(IJhandle h);
  109.  
  110. /*
  111.  * get a name suitable to describe THIS flavor of the board you have
  112.  * selected.  This will return the appropriate string in cases like
  113.  * "Indy Video" vs. "Galileo Video".
  114.  *
  115.  * string belongs to ij and is valid as long as this IJhandle is alive.
  116.  */
  117. char *ijGetDeviceName(IJhandle h);
  118.  
  119. /*
  120.  * get number of jacks for this handle
  121.  */
  122. int ijGetNumJacks(IJhandle h);
  123.  
  124. /*
  125.  * get a textual description of each input jack.
  126.  *
  127.  * string belongs to ij and is valid as long as this IJhandle is alive.
  128.  *
  129.  * idx should range from 0 to ijGetNumJacks() - 1
  130.  */
  131. char *ijGetJackName(IJhandle h, int idx); /* from 0 to NumJacks-1 */
  132.  
  133. /*
  134.  * how to choose a jack:
  135.  *
  136.  * you pick a jack by specifying an index idx from 0 to ijGetNumJacks() - 1,
  137.  * or you can pick the jack currently selected in vcp by passing VL_ANY
  138.  * for idx.
  139.  *
  140.  * use the following functions in this way to create a properly 
  141.  * configured path from that jack to your specified drain_node:
  142.  *
  143.   { 
  144.     ... create IJhandle h and drain node drain_node, pick idx ...
  145.     int node_number = ijGetNodeNumber(h, idx);
  146.     VLDev device = ijGetVLDev(h);
  147.     VLNode source_node = vlGetNode(svr, VL_SRC, VL_VIDEO, node_number);
  148.     VLPath path = vlCreatePath(svr, device, source_node, drain_node);
  149.     
  150.     if (node_number < 0 || source_node < 0 || path < 0) 
  151.       return FALSE;
  152.     
  153.     if (vlSetupPaths(svr, (VLPathList)&path, 1, VL_SHARE, VL_SHARE) < 0)
  154.       { vlDestroyPath(svr, path); return FALSE; }
  155.     
  156.     if (ijConfigurePath(h, idx, 
  157.                         source_node, drain_node, path, 
  158.                         node_number, ret_idx))
  159.       { vlDestroyPath(svr, path); return FALSE; }
  160.   }
  161.  * 
  162.  * as you can see here, jack selection in the VL consists of two parts:
  163.  * first you must choose the right VLNode and set up a path containing that
  164.  * node, and then you must properly configure the node.  in the VL, each
  165.  * VL_VIDEO, VL_SRC node can serve one or more input jacks, and the choice
  166.  * of video node and its required settings are totally device-dependent.
  167.  * ij handles the device-dependent aspects for you.
  168.  *
  169.  * ijGetNodeNumber() returns a video source node number which lets
  170.  * you create the video source node. 
  171.  *
  172.  * once you have created the node and path and set up the path,
  173.  * you now pass control back to ijConfigurePath() which does the
  174.  * necessary vlSetControl()s to configure your path to input
  175.  * data from the requested jack.
  176.  *
  177.  * the index of the actual jack chosen is returned in *ret_idx if
  178.  * ret_idx is non-NULL.  this is how you tell which is the default jack.
  179.  *
  180.  * ijGetNodeNumber() and ijConfigurePath return <0 on failure.
  181.  * no error return values are provided now, except for VLErrno.
  182.  *
  183.  * you can call this routine as many times as you like with different
  184.  * arguments.  calling this function does not change the state of the 
  185.  * IJhandle in any way.  ij does not store the VLPath, VLNodes, index,
  186.  * or node number it returns in the handle at all.
  187.  *
  188.  * VL CRAP:
  189.  *
  190.  * Q: why doesn't ij provide a quicky routine that just returns you an
  191.  * already-configured node and path?
  192.  *
  193.  * A: to do this, IJ would need to create the source node, because 
  194.  * the video source node number varies by jack in the VL.
  195.  *
  196.  * then, ij would need to create the path, because we need to set controls
  197.  * on the nodes we create, and VL only lets you set controls on a node if 
  198.  * you also specify the path the node is on!  argh!  
  199.  *
  200.  * then, ij would need to set up the paths, since the VL only lets you set
  201.  * controls on a path which is set up!  argh!!  vlSetupPaths() is a 
  202.  * critical operation whose arguments and return value are of great 
  203.  * importance to an app;  it would be difficult to do this inside ij
  204.  * without removing critical control from the app.  what's worse, 
  205.  * some apps want to pass more than one path at a time to 
  206.  * vlSetupPaths so that the resource allocation is atomic.  this
  207.  * would not be possible if ij did the path setup.
  208.  *
  209.  * Q: why isn't there a function you can call to simply return the current
  210.  * jack rather than creating a path?  
  211.  *
  212.  * A: because in VL, you CAN'T get the current jack without creating a path.
  213.  * argh!
  214.  * 
  215.  * the notion of "current jack" in VL is complicated.  the current jack
  216.  * selected on vcp is the current jack on the current VL default source 
  217.  * node.  ij determines the current default souce node by creating a 
  218.  * device path, setting it up VL_READ_ONLY, VL_READ_ONLY, reading 
  219.  * its node number from the control VL_DEFAULT_SOURCE, and destroying
  220.  * the path.  Then it gets a handle to that node, opens up a path on 
  221.  * that node, and determines which jack is the current jack on that node 
  222.  * by getting various device-dependent VL controls on that node.  
  223.  * it is truly unfortunate that VL users must deal with this.
  224.  *
  225.  */
  226. int ijGetNodeNumber(IJhandle h, int idx);
  227.  
  228. int ijConfigurePath(IJhandle h, int idx,
  229.                     VLNode source_node, VLNode drain_node, VLPath path,
  230.                     int node_number, int *ret_idx);
  231.  
  232.  
  233. /*
  234.  * when you get a VLControlChanged event, pass in the type of the
  235.  * VL control which changed, and this function will return 1
  236.  * if that control could affect the choice of input jack, or 0
  237.  * if not.  see the Q and A below to see why you would want to
  238.  * do this.
  239.  */
  240. int ijDoesControlAffectInputJack(IJhandle h, VLControlType type) ;
  241.  
  242.  
  243. /*
  244.  * Some questions and answers about input jack selection:
  245.  *
  246.  * Q: what to do when the user chooses a different jack in vcp?
  247.  *
  248.  * A: when this happens, one of two things occurs:
  249.  *
  250.  * - if the user changes the default source node in vcp (usually 
  251.  *   this looks like a "default in" menu), your app will receive a 
  252.  *   VLDefaultSource event.
  253.  * - if the user changes the current jack on the default source node, 
  254.  *   your app will receive a VLControlChanged event for the relevant controls.
  255.  *   many menus on vcp could change the current jack on the default source 
  256.  *   node.
  257.  *
  258.  * if the default source node changes, and you want to track vcp, 
  259.  * you MUST destroy and recreate the node and path, since the current
  260.  * jack now resides on a new VLNode.
  261.  *
  262.  * if the jack on the default source node changes, then technically you
  263.  * don't have to destroy and recreate the node and path, but you might as well
  264.  * do it anyway.
  265.  *
  266.  * so, to track changes in vcp, 
  267.  *
  268.  * - add VLDefaultSourceMask|VLControlChangedMask to your event mask.  
  269.  * - when you receive a VLDefaultSource event, destroy your node and path,
  270.  *   and call ijGetNodeCreatePath() again with an argument of VL_ANY for idx.
  271.  *   ijGetNodeCreatePath() will return the index of the newly chosen jack.
  272.  * - when you receive a VLControlChanged event, check to see whether the 
  273.  *   control that changed could affect the current input jack, and if so, 
  274.  *   do the same as if you had received a VLDefaultSource event.
  275.  *   Determining whether the VLControlChanged event could cause an input
  276.  *   jack change is---you guessed it---device-dependent.  Use 
  277.  *   ijDoesControlAffectInputJack() to determine this (see above).
  278.  *
  279.  *
  280.  * Q: what if I want my app to be totally independent of vcp?
  281.  *
  282.  * A: sorry, bud.  the system was just not designed that way.
  283.  * on most SGI devices, the available input jacks are separated 
  284.  * into groups, and the hardware is only designed to take in data 
  285.  * from ONE jack per group at a time.  for example, an ev1 board has 
  286.  * up to 4 analog video inputs, but only one of those inputs can be 
  287.  * used for video->memory or video->screen paths at a time.  This is  
  288.  * true even if the paths in question are owned by totally separate 
  289.  * processes--the choice of a jack from the group of analog input
  290.  * jacks device-global.  So, when a user goes and changes the 
  291.  * "analog input source" setting on vcp, or any other app running on 
  292.  * the system changes the same control, your app WILL start getting 
  293.  * data from a different jack, and you cannot control or lock out this
  294.  * behavior in any way.
  295.  *
  296.  * the "groups" of jacks are represented in the VL as separate VLNodes.
  297.  * the selection of a jack within a particular VLNode is done by
  298.  * setting controls on that node, usually (but not always) VL_MUXSWITCH.
  299.  * on all devices so far, the VL_MUXSWITCH (or comparable) setting on a 
  300.  * VLNode is device-global, meaning that it affects all other VLNodes 
  301.  * with the same node number.  Only when different jacks are present
  302.  * on different VLNodes can you use them simultaneously.
  303.  *
  304.  * this lame behavior can be found in: vino, ev1, sirius, and impactvid.
  305.  * future devices may or may not exhibit this behavior.
  306.  *
  307.  * given this, the best you can achieve is to be "sort of" independent 
  308.  * of vcp.  sometimes, when people mess with vcp, it will affect your
  309.  * app.  sometimes, it will not.
  310.  *
  311.  * our video hardware and VL software have left us with only one way
  312.  * of avoiding this usability nightmare, one way to present consistent
  313.  * behavior: make your app input from whatever jack is selected in vcp.
  314.  * if the user selects a new jack in vcp, then your app changes
  315.  * immediately.  this behavior would be consistently true regardless
  316.  * of which jack selection control the user futzed with---your app
  317.  * would not behave differently if the user changed "analog input source"
  318.  * versus "default in," as many do now.  The GUI user knows nothing
  319.  * about VL nodes or VL_MUXSWITCH controls, and it is silly expecting
  320.  * the user to understand such concepts when all they want to do
  321.  * is input video from ONE jack (which is what the vast majority 
  322.  * want to do).  If the user is doing a task where they really need
  323.  * two input jacks, then sure, go ahead and expose the subtleties.
  324.  * but if your app just needs to pick one input jack, and it doesn't 
  325.  * specifically need to pick a different jack than other apps which 
  326.  * are running, it may not be worthwhile for you to try and make your 
  327.  * app independent of vcp.  you will only present a user interface 
  328.  * which is inconsistent with vcp and confusing.
  329.  *
  330.  *
  331.  * Q: what to do when the user chooses a different jack in my app?
  332.  *
  333.  * A: destroy the node and the path yourself, and call 
  334.  * ijGetNodeCreatePath again.
  335.  *
  336.  * on the same theory of keeping your app consistent with vcp,
  337.  * you would presumably want to make sure that vcp reflected
  338.  * the new default input jack.  as with the question above,
  339.  * SOME of vcp's controls will automatically reflect your
  340.  * new choice of jack, because they are device-global controls.
  341.  * but not all of them.  In order to keep vcp consistent, you
  342.  * would have to set the default source node to the node number
  343.  * of the newly selected jack.  This would mean setting the
  344.  * VL_DEFAULT_SOURCE parameter on the device node for the
  345.  * device (XXX will VL let you do this? checking...)
  346.  *
  347.  */
  348.  
  349.  
  350.  
  351.